const webpack = require('webpack');
const ipFile = require('./build/ip')
const glob = require('glob');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin'); // 插件主要是为了抽离css样式，防止将样式打包在 js中引起页面样式加载错乱的现象
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 自动清除上一次打包构建目录文件
const TerserPlugin = require('terser-webpack-plugin');
// console.log('\n\n\n',resolve('layer'));
// // src\assets\lib\layer1\layer.js
// console.log('\n\n\n');

function resolve(dir) {
  return path.join(__dirname, '.', dir)
}

const webpackconfig = {
  entry: addEntry,
  output: {
    filename: '[name].[hash:8].js',
    path: __dirname + '/dist',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /(node_modules)/, // 排除文件
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      // {
      //   test: /\.css$/,
      //   use: [
      //     { loader: 'style-loader' },
      //     {
      //       loader: 'css-loader',
      //       options: {
      //         modules: true,
      //         getLocalIdent: (context, localIdentName, localName, options) => {
      //           return localName
      //         }
      //       }
      //     },
      //   ]
      // },
      {
        test: /\.scss$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                require("autoprefixer") /*在这里添加*/
              ]
            }
          },
          {
            loader: 'sass-loader',
          }
        ]
      },
      {
        test: /\.(png|jpg|git|jpeg)$/,
        use: [{
          loader: 'url-loader',
          options: {
            limit: 10240, // 当图片小于10k，会对图片进行base64转换
            name: '[name].[ext]',
            publicPath: '../img/',
            outputPath: 'img/'
          }
        }
        ]
      },
      // html中的img图片处理
      {
        test: /\.(html)$/,
        use: {
          loader: 'html-loader',
          options: {
            attrs: ['img:src', 'img:data-src', 'audio:src'],
            minimize: true
          }
        }
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              name: '[name].[ext]',// 打包后的文件名称
              outputPath: '', // 默认是dist目录
              publicPath: '../font/', // 图片的url前面追加'../font'
              useRelativePath: true, // 使用相对路径
              limit: 50000 // 表示小于1K的图片会被转化成base64格式
            }
          }
        ]
      },
      //暴露$和jQuery到全局
      {
        test: require.resolve('jquery'), //require.resolve 用来获取模块的绝对路径
        use: [
          { loader: 'expose-loader', options: 'jQuery' },
          { loader: 'expose-loader', options: '$' }
        ]
      },
      // //暴露$和layer到全局
      // {
      //   test: require.resolve('layer'), //require.resolve 用来获取模块的绝对路径
      //   use: [
      //     { loader: 'expose-loader', options: 'layer' }
      //   ]
      // },
    ]
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': resolve('src'),
      jquery: 'jquery/dist/jquery.min.js',
      // 定义别名和插件位置
      'mui': path.resolve(__dirname, './src/assets/lib/mui/js/mui.js'),
      'layer': path.resolve(__dirname, './src/assets/lib/layer/layer.js'),
    },
  },
  plugins: [
    new webpack.ProvidePlugin({
      mui: "mui",
      "window.mui": "mui",
      $: "jquery",
      jQuery: "jquery",
      jq: "jquery",
      layer: "layer",
    }),
    // new webpack.ProgressPlugin(), // 打包进程
    new webpack.HotModuleReplacementPlugin(), // 启用 HMR,

    new webpack.NamedModulesPlugin(), // 在控制台中输出可读的模块名

    new webpack.HashedModuleIdsPlugin(), // 不做改动hash保持不变

    new CleanWebpackPlugin({
      verbose: true,
    }),
  ],
  // 公共代码抽取，webpack4 已弃用 CommonsChunkPlugin ，使用optimization.splitChunks 代替
  // 提取被重复引入的文件，单独生成一个或多个文件，这样避免在多入口重复打包文件
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          chunks: 'all', // 选择全部chunk ，all, async, initial 三选一, 插件作用的chunks范围
          name: 'vendor', // 生成的公共代码文件名，惯用vendor
          test: /[\\/]node_modules[\\/]/,  // 作用于
          minChunks: 3, // 最小chunks，提取至少3个模块共有的部分
          maxInitialRequests: 5, // 最大初始化chunks
          minSize: 0 // 最小尺寸
        }
      }
    },
    // 压缩代码，默认开启
    minimize: true,
    // 压缩配置
    minimizer: [
      new TerserPlugin({
        include: /\.min\.js$/
      }),
    ],
    runtimeChunk: true
  },
  devServer: {
    hot: true,
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    host: ipFile.getIp(),
    port: 8078
  },
  mode: 'none'
}
module.exports = webpackconfig;

// 动态引入 入口文件
// 搜索并收集文件
function addEntry() {
  const entry = {};
  entry.main = './src/main.js'; // 公共目录引进
  let arr = glob.sync('./src/pages/*/*/index.js');
  //读取src目录所有page入口
  arr.forEach(function (filePath) {
    var nameArr = filePath.match(/\/pages\/(.+)\/index.js/);
    let nameArr1 = nameArr[1].split('/');
    let name = nameArr1[1];
    entry[name] = filePath;
  });

  return entry;
};

function getEntry() {
  let globPath = './src/pages/*/*/*.html'
  // (\/|\\\\) 这种写法是为了兼容 windows和 mac系统目录路径的不同写法
  let pathDir = 'src(\/|\\\\)(.*?)(\/|\\\\)html'
  let files = glob.sync(globPath)

  let dirname, entries = []
  for (let i = 0; i < files.length; i++) {
    dirname = path.dirname(files[i])
    let val = dirname.replace(new RegExp('^' + pathDir), '$2');
    entries.push(val)

  }
  return entries // ['pages\about','pages\home']
}

initHtmlWebpackPlugin();
// 自动生成多页面模板
function initHtmlWebpackPlugin() {
  let arr = getEntry();
  let pagesArr = []
  arr.forEach(obj => {
    let lastSysbolIndex = obj.lastIndexOf('/');
    let name = obj.substr(lastSysbolIndex + 1)
    pagesArr.push(name);
  });

  arr.forEach((pathname, i) => {

    // 排除其他页面模块的js
    let lastSysbolIndex = pathname.lastIndexOf('/');
    let curPageName = pathname.substr(lastSysbolIndex + 1)
    let runPageName = 'runtime~' + curPageName;
    let excludeChunksArr = pagesArr.filter(pageName => {
      let flag = true // false 那么就表示本次循环的不添加该值
      if (pageName === curPageName || pageName === runPageName) {
        flag = false
      }
      return flag
    });

    let fileName = path.join(pathname) + '.html';
    let template = path.join(__dirname, pathname, 'index.html');

    let fileArr = fileName.split('\\');
    fileArr = fileArr.reverse();
    fileName = [fileArr[1], fileArr[0]].join('\\')

    let conf = {
      filename: fileName, // pages\about.html
      template: template, //  H:\kaiking\study\webpackTest03\src\pages\about\html\index.html
      inject: true,
      hash: true,
      excludeChunks: excludeChunksArr, // 排除指定的模快
      minify: { // 压缩HTML文件
        removeAttributeQuotes: true, //删除属性双引号
        removeComments: true, // 移除注释
        collapseWhitespace: true, // 压缩空白
        removeRedundantAttributes: true, // 当值匹配默认值时删除属性
        useShortDoctype: true, // 使用短的doctype替代doctype
        removeEmptyAttributes: true, // 移除空属性
        removeStyleLinkTypeAttributes: true, // 从style和link标签中删除type='text/css'
        keepClosingSlash: true, // 保留单例元素的末尾斜杠。
        minifyJS: true, // 在脚本元素和事件属性中缩小JavaScript(使用UglifyJS)
        minifyCSS: true, // 压缩内联css
        minifyURLs: true // 在各种属性中缩小url
      }
    }

    webpackconfig.plugins.push(new HtmlWebpackPlugin(conf))
  })
}

// initExtractCss(); // 自动抽取页面css 为每个页面定义一个 ExtractTextPlugin
// 自动抽取页面css 为每个页面定义一个 ExtractTextPlugin
function initExtractCss() {
  let arr1 = glob.sync('./src/pages/*/css/*.scss');
  let arr2 = glob.sync('./src/pages/*/css/*.css');
  let arr = arr1.concat(arr2);

  arr.forEach(pathname => {

    const pageExtractCss = new ExtractTextPlugin(pathname + '/[name].[contenthash:8].css');

    var reg = new RegExp('src(\\|\/)' + pathname + '(\\|\/)css(\\|\/).*\.(css|scss)$', 'i');
    let extensionsObj = {
      test: reg,
      use: pageExtractCss.extract({
        fallback: 'style-loader',
        use: ['css-loader', 'postcss-loader', 'sass-loader']
      })
    }

    webpackconfig.module.rules.push(extensionsObj)
    webpackconfig.plugins.push(pageExtractCss)
  })
}
